package com.cloud.utils;

import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.List;

/**
 * 桩号转经纬度
 *
 * @author yzj
 */
public class GisStakeUtils {

    /**
     * 桩号转化为坐标
     *
     * @param stakeNum  输入的桩号 例:1210.2或者k1210.22
     * @param stakeCode 起始桩号数 1210
     * @param sPoint    起始桩号坐标 1210 对应坐标
     * @param nPoint    下一桩号坐标 1211 对应的坐标
     * @param pointList 路径规划返回规划点集合
     * @return
     */
    public static Point2D.Double stakeToPoint(String stakeNum, String stakeCode, Point2D.Double sPoint,
                                              Point2D.Double nPoint, List<Point2D.Double> pointList) {
        if (StringUtils.isNull(sPoint) || StringUtils.isNull(nPoint)) {
            return null;
        }
        // 用于存储相邻点间距离
        List<Double> lenArr = new ArrayList();
        // 事发起点和路径规划点集合,用于计算个点之间距离
        List<Point2D.Double> tempArr = new ArrayList();
        if (pointList.size() > 0) {
            tempArr.add(sPoint);
            tempArr.addAll(pointList);
        }
        // 循环遍历取每相邻2个点距离
        for (int i = 0; i < tempArr.size() - 1; i++) {
            lenArr.add(getPointDistance(tempArr.get(i), tempArr.get(i + 1)));
        }
        Point2D.Double pointVo = null;
        if (stakeNum.indexOf("k") >= 0 || stakeNum.indexOf("K") >= 0) {
            stakeNum = stakeNum.substring(1, stakeNum.length());
        }
        // 输入点与最近起点距离,例:1210.2-1210
        double offSet = Double.parseDouble(stakeNum) - Double.parseDouble(stakeCode);
        // 看路径规划后离输入点最近的2个点
        double length = 0d;
        int index = 0;
        if (pointList.size() > 2 && offSet > 0) {
            for (int i = 0; i < lenArr.size(); i++) {
                index = i;
                if (offSet > length && offSet < length + lenArr.get(i)) {
                    break;
                }
                length += lenArr.get(i);
            }
            if (length == 0) {
                pointVo = getStakeToPoint((offSet - length), sPoint, pointList.get(index));
            } else {
                pointVo = getStakeToPoint((offSet - length), pointList.get(index - 1), pointList.get(index));
            }
        } else {
            pointVo = getStakeToPoint(offSet, pointList.get(0), pointList.get(1));
        }
        return pointVo;
    }

    /**
     * 计算两点间距离
     *
     * @param offSet 离路径规划后最近起始点的距离
     * @param sPoint 离路径规划后最近起始点坐标
     * @param nPoint 离路径规划后最近终止点坐标
     * @return
     */
    private static Point2D.Double getStakeToPoint(double offSet, Point2D.Double sPoint, Point2D.Double nPoint) {
        double distance = getPointDistance(sPoint, nPoint);
        if (distance == 0) {
            distance = offSet;
        }
        // 算出对应经纬度,看成1条直线,因为已经尽肯能精度了
        // 如果系数大于1则设置为0.9，避免错乱
        double ratio = (offSet / distance) <= 1 ? (offSet / distance) : 0.9;
        double offSetX = (ratio * (nPoint.getX() - sPoint.getX())) + sPoint.getX();
        double offSetY = (ratio * (nPoint.getY() - sPoint.getY())) + sPoint.getY();
        return new Point2D.Double(offSetX, offSetY);
    }

    /**
     * 计算两点间距离
     *
     * @param sPoint 起始桩号坐标
     * @param nPoint 终止桩号坐标
     * @return
     */
    private static double getPointDistance(Point2D.Double sPoint, Point2D.Double nPoint) {
        return GisPointUtils.getDistance(sPoint.getX(), sPoint.getY(), nPoint.getX(), nPoint.getY());
    }

}
